import Gird, { GRID_TYPE } from "./common";
import mapCtl from "./mapCtl";


const { ccclass, property } = cc._decorator;

@ccclass
export default class control extends cc.Component {

    @property(mapCtl)
    mapGraph: mapCtl = null;
    @property(cc.Vec2)
    startPos: cc.Vec2 = cc.v2(5, 10);
    @property(cc.Vec2)
    endPos: cc.Vec2 = cc.v2(30, 10);
    @property(cc.Prefab)
    labPre: cc.Prefab = null

    open_set = []
    close_set = []
    end_set = []
    targetIndex = 1
    // LIFE-CYCLE CALLBACKS:

    // onLoad () {}

    start() {
        this.open_set = []
        this.SetStartAndEnd()
        this.SetBarrierGrp()
        this.FindWay()
    }

    // update (dt) {}
    /**
     * 设置开始与终点位置
     */
    SetStartAndEnd() {
        this.mapGraph.drawCube(this.startPos, cc.Color.GREEN);
        this.mapGraph.drawCube(this.endPos, cc.Color.RED)

        let startPoint = new Gird()
        startPoint.x = this.startPos.x
        startPoint.y = this.startPos.y
        this.open_set.push(startPoint)
        console.log(this.open_set)
    }
    /**
     * 暂时使用的障碍物
     */
    SetBarrierGrp() {
        for (let i = 0; i < 15; i++) {
            this.mapGraph.drawCube(cc.v2(20, 5 + i), cc.Color.BLUE)
            let gridInfo = new Gird()
            gridInfo.x = 20;
            gridInfo.y = 5 + i
            gridInfo.type = GRID_TYPE.Type_0
            this.close_set.push(gridInfo)
        }
    }

    /**
     * 判断是否在open_set里面
     */
    IsInOpen_set(gridData: Gird) {
        let isHave = false
        for (let i = 0; i < this.open_set.length; i++) {
            if (this.open_set[i].x == gridData.x && this.open_set[i].y == gridData.y) {
                isHave = true
                break
            }
        }
        return isHave
    }

    getInOpen_setData(Nx: number, Ny: number) {
        let index
        for (let i = 0; i < this.open_set.length; i++) {
            if (this.open_set[i].x == Nx && this.open_set[i].y == Ny) {
                index = i
                break
            }
        }
        return this.open_set[index]
    }

    /**
     * 判断是否在close_set里面
     */
    IsInClose_set(gridData: Gird) {
        let isHave = false
        for (let i = 0; i < this.close_set.length; i++) {
            if (this.close_set[i].x == gridData.x && this.close_set[i].y == gridData.y) {
                isHave = true
                break
            }
        }
        return isHave
    }

    FindWay() {
        this.open_set.sort(this.sortFunc);
        let targetGrid = this.open_set[0];
        if (targetGrid.x == this.endPos.x && targetGrid.y == this.endPos.y) {
            //找到了终点，输出关系链,并打印出来
            console.log("end   ", targetGrid)
            this.DrawEndLine(targetGrid)
        } else {
            this.scheduleOnce(() => {
                this.DrawTargetGrid(targetGrid)
                this.GetGroundPoint(targetGrid)
                this.creatLabPre(targetGrid)
            }, 0.01)
        }
    }

    DrawTargetGrid(gridData: Gird) {
        this.mapGraph.drawCube(cc.v2(gridData.x, gridData.y), cc.Color.ORANGE)
    }
    DrawEndLine(gridData: Gird) {
        this.end_set.push(gridData)
        this.mapGraph.drawCube(cc.v2(gridData.x, gridData.y), cc.Color.YELLOW);
        if (gridData.x != this.startPos.x || gridData.y != this.startPos.y) {
            this.DrawEndLine(gridData.parent)
        }
    }

    creatLabPre(cubeInfo: Gird) {
        let pre = cc.instantiate(this.labPre)
        pre.parent = this.mapGraph.node
        pre.setPosition(cubeInfo.x * 50 + 25, cubeInfo.y * 50 + 25)
        pre.getComponent('labPre').setFlab(cubeInfo)

    }

    /**
     * 获取锚点周围的一圈
     * @param pointGrid 锚点
     */
    GetGroundPoint(pointGrid: Gird) {
        this.DeletOpen_setData(pointGrid);
        for (let i = -1; i <= 1; i++) {
            for (let j = -1; j <= 1; j++) {
                if (pointGrid.x + i < 0 || pointGrid.y + j < 0)
                    continue
                let data = new Gird()
                data.x = pointGrid.x + i
                data.y = pointGrid.y + j
                data.g = pointGrid.g + (Math.sqrt(Math.pow(i * 10, 2) + Math.pow(j * 10, 2)));                                        //(i == 0 || j == 0) ? 1 : 1.4              //要是有x或y=0跟锚点在同一x、y坐标内，则说明距离较近，否则是斜角线
                data.h = Math.abs(this.endPos.x - data.x) * 10 + Math.abs(this.endPos.y - data.y) * 10;
                data.f = data.g + data.h
                let inOpen_set = this.IsInOpen_set(data)
                let inClose_set = this.IsInClose_set(data)
                //判断新生成的格子是否在opendata里面或者在closedata里面
                if (inClose_set) {
                    //在close_set内，忽略
                    data = null
                    continue
                } else if (inOpen_set) {
                    //在open_set内，根据已有的parent判断g是否比原来的更小,是的话，修改父节点
                    let haveData = this.getInOpen_setData(data.x, data.y);
                    if ((data.g + pointGrid.g) < haveData.g) {
                        console.log('fashengle ')
                        haveData.parent = pointGrid
                        haveData.g = (data.g + pointGrid.g)
                        haveData.f = haveData.g + haveData.h
                    }
                } else if (!inOpen_set && !inClose_set) {
                    //不在open_set且不在close_set中
                    data.parent = pointGrid
                    this.open_set.push(data)
                } else {
                    data = null
                    continue
                }
            }
        }
        this.FindWay()
    }
    /**
     * 从open_set中删除锚点信息，将其移到closeData
     * @param gridData 锚点
     */
    DeletOpen_setData(gridData: Gird) {
        for (let i = 0; i < this.open_set.length; i++) {
            if (this.open_set[i].x == gridData.x && this.open_set[i].y == gridData.y) {
                this.open_set.splice(i, 1)
                this.close_set.push(gridData)
                break
            }
        }
    }

    sortFunc(x, y) {
        return x.f - y.f;
    }



}
